bitkeeper revision 1.860 (40767158VSrp08a0j4zL0drGEP4xNg)
authorkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>
Fri, 9 Apr 2004 09:48:08 +0000 (09:48 +0000)
committerkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>
Fri, 9 Apr 2004 09:48:08 +0000 (09:48 +0000)
Synchronously flush console data when a domain dies.

.rootkeys
xenolinux-2.4.25-sparse/arch/xen/drivers/console/console.c
xenolinux-2.4.25-sparse/arch/xen/kernel/ctrl_if.c
xenolinux-2.4.25-sparse/arch/xen/kernel/process.c
xenolinux-2.4.25-sparse/arch/xen/kernel/setup.c
xenolinux-2.4.25-sparse/include/asm-xen/ctrl_if.h
xenolinux-2.4.25-sparse/kernel/panic.c [deleted file]

index 1ca38ee6f81e7c2ec64906bc3f1f3651d94ba075..1938f8edbb3ae207c0554b866f0c66f9caa57614 100644 (file)
--- a/.rootkeys
+++ b/.rootkeys
 3e5a4e686V0nioX2ZpFf056sgvdiQw xenolinux-2.4.25-sparse/include/linux/sunrpc/debug.h
 401c0592pLrp_aCbQRo9GXiYQQaVVA xenolinux-2.4.25-sparse/include/linux/timer.h
 3e5a4e68W_hpMlM3u_-QOKMp3gzcwQ xenolinux-2.4.25-sparse/init/do_mounts.c
-3e5a4e68TJJavrunYwTAnLRSBxSYqQ xenolinux-2.4.25-sparse/kernel/panic.c
 3f9d4b44247udoqWEgFkaHiWv6Uvyg xenolinux-2.4.25-sparse/kernel/time.c
 401c059bjLBFYHRD4Py2uM3eA1D4zQ xenolinux-2.4.25-sparse/kernel/timer.c
 3e6e7c1efbQe93xCvOpOVCnXTMmQ5w xenolinux-2.4.25-sparse/mkbuildtree
index 32877901622f8a13012c8ea81fc8e3e4e856987e..a6ee3468570ddf8ad2bf9295414dafa4fa5fcc44 100644 (file)
@@ -50,6 +50,7 @@ static struct tq_struct xencons_tx_flush_task = {
     routine: xencons_tx_flush_task_routine
 };
 
+
 /******************** Kernel console driver ********************************/
 
 static void kcons_write(
@@ -112,7 +113,7 @@ void xen_console_init(void)
 }
 
 
-/*** Useful function for console debugging -- goes straight to Xen ****/
+/*** Useful function for console debugging -- goes straight to Xen***/
 asmlinkage int xprintk(const char *fmt, ...)
 {
     va_list args;
@@ -133,6 +134,45 @@ asmlinkage int xprintk(const char *fmt, ...)
     return 0;
 }
 
+/*** Forcibly flush console data before dying. ***/
+void xencons_force_flush(void)
+{
+    ctrl_msg_t msg;
+    int        sz;
+
+    /* Emergency console is synchronous, so there's nothing to flush. */
+    if ( start_info.flags & SIF_INITDOMAIN )
+        return;
+
+    /*
+     * We use dangerous control-interface functions that require a quiescent
+     * system and no interrupts. Try to ensure this with a global cli().
+     */
+    cli();
+
+    /* Spin until console data is flushed through to the domain controller. */
+    while ( (wc != wp) && !ctrl_if_transmitter_empty() )
+    {
+        /* Interrupts are disabled -- we must manually reap responses. */
+        ctrl_if_discard_responses();
+
+        if ( (sz = wp - wc) == 0 )
+            continue;
+        if ( sz > sizeof(msg.msg) )
+            sz = sizeof(msg.msg);
+        if ( sz > (WBUF_SIZE - WBUF_MASK(wc)) )
+            sz = WBUF_SIZE - WBUF_MASK(wc);
+
+        msg.type    = CMSG_CONSOLE;
+        msg.subtype = CMSG_CONSOLE_DATA;
+        msg.length  = sz;
+        memcpy(msg.msg, &wbuf[WBUF_MASK(wc)], sz);
+            
+        if ( ctrl_if_send_message_noblock(&msg, NULL, 0) == 0 )
+            wc += sz;
+    }
+}
+
 
 /******************** User-space console driver (/dev/console) ************/
 
@@ -431,7 +471,7 @@ static void xencons_close(struct tty_struct *tty, struct file *filp)
     MOD_DEC_USE_COUNT;
 }
 
-int __init xencons_init(void)
+static int __init xencons_init(void)
 {
     memset(&xencons_driver, 0, sizeof(struct tty_driver));
     xencons_driver.magic           = TTY_DRIVER_MAGIC;
@@ -481,7 +521,7 @@ int __init xencons_init(void)
     return 0;
 }
 
-void __exit xencons_fini(void)
+static void __exit xencons_fini(void)
 {
     int ret;
 
@@ -501,4 +541,3 @@ void __exit xencons_fini(void)
 
 module_init(xencons_init);
 module_exit(xencons_fini);
-
index 4c43d091e766a709c5d1610a7e651d0d97c821cd..4002ae4c618ea761032a67539422ab9789090bd4 100644 (file)
@@ -315,3 +315,20 @@ void __init ctrl_if_init(void)
 
     ctrl_if_resume();
 }
+
+
+/*
+ * !! The following are DANGEROUS FUNCTIONS !!
+ * Use with care [for example, see xencons_force_flush()].
+ */
+
+int ctrl_if_transmitter_empty(void)
+{
+    return (get_ctrl_if()->tx_req_prod == ctrl_if_tx_resp_cons);
+}
+
+void ctrl_if_discard_responses(void)
+{
+    ctrl_if_tx_resp_cons = get_ctrl_if()->tx_resp_prod;
+}
+
index 640179661b800e01a2b918e03086c484e055175f..1ef8521fcb9d9f9e21f09ba0f1dae9fed53b788c 100644 (file)
@@ -117,17 +117,20 @@ void cpu_idle (void)
 
 void machine_restart(char * __unused)
 {
+    /* We really want to get pending console data out before we die. */
+    extern void xencons_force_flush(void);
+    xencons_force_flush();
     HYPERVISOR_exit();
 }
 
 void machine_halt(void)
 {
-    HYPERVISOR_exit();
+    machine_restart(NULL);
 }
 
 void machine_power_off(void)
 {
-    HYPERVISOR_exit();
+    machine_restart(NULL);
 }
 
 extern void show_trace(unsigned long* esp);
@@ -207,7 +210,7 @@ void release_thread(struct task_struct *dead_task)
     if (dead_task->mm) {
         // temporary debugging check
         if (dead_task->mm->context.size) {
-            printk("WARNING: dead process %8s still has LDT? <%p/%p>\n",
+            printk("WARNING: dead process %8s still has LDT? <%p/%08x>\n",
                    dead_task->comm, 
                   dead_task->mm->context.ldt,
                   dead_task->mm->context.size);
index be7cc61efebc1c146bf04648b5f377d16e144a9a..6be85db7f1641150f57626ff5ac8dff3b7c1d818 100644 (file)
@@ -169,6 +169,11 @@ void __init setup_arch(char **cmdline_p)
     extern unsigned long cpu0_pte_quicklist[];
     extern unsigned long cpu0_pgd_quicklist[];
 
+    /* Force a quick death if the kernel panics. */
+    extern int panic_timeout;
+    if ( panic_timeout == 0 )
+        panic_timeout = 1;
+
 #ifndef CONFIG_HIGHIO
     blk_nohighio = 1;
 #endif
index c9e874bb0df55a8ee034af033ec07ed6212edb73..9d12487144a87132982a2ee702dd3cbf68cc67c1 100644 (file)
@@ -95,4 +95,20 @@ void ctrl_if_resume(void);
 /* Start-of-day setup. */
 void ctrl_if_init(void);
 
+/*
+ * Returns TRUE if there are no outstanding message requests at the domain
+ * controller. This can be used to ensure that messages have really flushed
+ * through when it is not possible to use the response-callback interface.
+ * WARNING: If other subsystems are using the control interface then this
+ * function might never return TRUE!
+ */
+int ctrl_if_transmitter_empty(void);  /* !! DANGEROUS FUNCTION !! */
+
+/*
+ * Manually discard response messages from the domain controller. 
+ * WARNING: This is usually done automatically -- this function should only
+ * be called when normal interrupt mechanisms are disabled!
+ */
+void ctrl_if_discard_responses(void); /* !! DANGEROUS FUNCTION !! */
+
 #endif /* __ASM_XEN__CONTROL_IF_H__ */
diff --git a/xenolinux-2.4.25-sparse/kernel/panic.c b/xenolinux-2.4.25-sparse/kernel/panic.c
deleted file mode 100644 (file)
index 9c96d92..0000000
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- *  linux/kernel/panic.c
- *
- *  Copyright (C) 1991, 1992  Linus Torvalds
- */
-
-/*
- * This function is used through-out the kernel (including mm and fs)
- * to indicate a major problem.
- */
-#include <linux/config.h>
-#include <linux/sched.h>
-#include <linux/delay.h>
-#include <linux/reboot.h>
-#include <linux/notifier.h>
-#include <linux/init.h>
-#include <linux/sysrq.h>
-#include <linux/interrupt.h>
-#include <linux/console.h>
-
-asmlinkage void sys_sync(void);        /* it's really int */
-
-int panic_timeout;
-
-struct notifier_block *panic_notifier_list;
-
-static int __init panic_setup(char *str)
-{
-       panic_timeout = simple_strtoul(str, NULL, 0);
-       return 1;
-}
-
-__setup("panic=", panic_setup);
-
-int machine_paniced; 
-
-/**
- *     panic - halt the system
- *     @fmt: The text string to print
- *
- *     Display a message, then perform cleanups. Functions in the panic
- *     notifier list are called after the filesystem cache is flushed (when possible).
- *
- *     This function never returns.
- */
-NORET_TYPE void panic(const char * fmt, ...)
-{
-       static char buf[1024];
-       va_list args;
-#if defined(CONFIG_ARCH_S390)
-        unsigned long caller = (unsigned long) __builtin_return_address(0);
-#endif
-
-#ifdef CONFIG_VT
-       disable_console_blank();
-#endif
-       machine_paniced = 1;
-       
-       bust_spinlocks(1);
-       va_start(args, fmt);
-       vsprintf(buf, fmt, args);
-       va_end(args);
-       printk(KERN_EMERG "Kernel panic: %s\n",buf);
-       if (in_interrupt())
-               printk(KERN_EMERG "In interrupt handler - not syncing\n");
-       else if (!current->pid)
-               printk(KERN_EMERG "In idle task - not syncing\n");
-       else
-               sys_sync();
-       bust_spinlocks(0);
-
-#ifdef CONFIG_SMP
-       smp_send_stop();
-#endif
-
-       notifier_call_chain(&panic_notifier_list, 0, NULL);
-
-       if (panic_timeout > 0)
-       {
-               /*
-                * Delay timeout seconds before rebooting the machine. 
-                * We can't use the "normal" timers since we just panicked..
-                */
-               printk(KERN_EMERG "Rebooting in %d seconds..",panic_timeout);
-               mdelay(panic_timeout*1000);
-               /*
-                *      Should we run the reboot notifier. For the moment Im
-                *      choosing not too. It might crash, be corrupt or do
-                *      more harm than good for other reasons.
-                */
-               machine_restart(NULL);
-       }
-#ifdef __sparc__
-       {
-               extern int stop_a_enabled;
-               /* Make sure the user can actually press L1-A */
-               stop_a_enabled = 1;
-               printk("Press L1-A to return to the boot prom\n");
-       }
-#endif
-#if defined(CONFIG_ARCH_S390)
-        disabled_wait(caller);
-#endif
-       sti();
-       for(;;) {
-#if defined(CONFIG_X86) && defined(CONFIG_VT) 
-               extern void panic_blink(void);
-               panic_blink(); 
-#endif
-               CHECK_EMERGENCY_SYNC
-#if defined(CONFIG_XEN)
-               HYPERVISOR_exit();
-#endif
-       }
-}
-
-/**
- *     print_tainted - return a string to represent the kernel taint state.
- *
- *     The string is overwritten by the next call to print_taint().
- */
-const char *print_tainted()
-{
-       static char buf[20];
-       if (tainted) {
-               snprintf(buf, sizeof(buf), "Tainted: %c%c",
-                       tainted & 1 ? 'P' : 'G',
-                       tainted & 2 ? 'F' : ' ');
-       }
-       else
-               snprintf(buf, sizeof(buf), "Not tainted");
-       return(buf);
-}
-
-int tainted = 0;
-
-/*
- * A BUG() call in an inline function in a header should be avoided,
- * because it can seriously bloat the kernel.  So here we have
- * helper functions.
- * We lose the BUG()-time file-and-line info this way, but it's
- * usually not very useful from an inline anyway.  The backtrace
- * tells us what we want to know.
- */
-
-void __out_of_line_bug(int line)
-{
-       printk("kernel BUG in header file at line %d\n", line);
-
-       BUG();
-
-       /* Satisfy __attribute__((noreturn)) */
-       for ( ; ; )
-               ;
-}